<?php
declare(strict_types=1);

namespace App\Middleware;

use App\Constants\XZXResponseCode;
use App\Model\Dao\SysAdminMchRelationDao;
use App\Utils\CustomUtils;
use Hyperf\Di\Annotation\Inject;
use Hyperf\HttpServer\Contract\ResponseInterface as HttpResponse;
use Hyperf\Utils\Context;
use Phper666\JWTAuth\JWT;
use Phper666\JWTAuth\Middleware\JWTAuthMiddleware;
use Phper666\JWTAuth\Util\JWTUtil;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;

/**
 * Class AdminJWTAuthMiddleware
 * TODO::鉴权中间件
 *
 * @package App\Middleware
 */
class AdminJWTAuthMiddleware extends JWTAuthMiddleware {

    /**
     * @var JWT
     */
    protected $jwt;

    /**
     * @var HttpResponse
     */
    protected $response;

    /**
     * @var SysAdminMchRelationDao
     * @Inject()
     */
    protected $SysAdminMchRelationDao;


    public function __construct (HttpResponse $response, JWT $jwt) {
        parent::__construct($response, $jwt);
    }

    /**
     * @param ServerRequestInterface  $request
     * @param RequestHandlerInterface $handler
     *
     * @return ResponseInterface
     * @throws \Psr\SimpleCache\InvalidArgumentException
     */
    public function process (ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface {

        $isValidToken = false;

        $token = $request->getHeaderLine('Authorization') ?? '';

        $data = null;

        if (strlen($token) > 0) {

            $token = JWTUtil::handleToken($token);

            if ($token !== false) {
                try {
                    $this->jwt->checkToken($token);
                } catch (\Throwable $th) {
                    throw new \Exception(XZXResponseCode::getMessage(XZXResponseCode::TOKEN_EXPIRE_CODE), XZXResponseCode::TOKEN_EXPIRE_CODE);
                }
                $isValidToken = true;
            }

            $data = $this->jwt->getParserData();
            if ($data['jwt_scene'] != 'adminapi') {
                $isValidToken = false;
            }

            if ($data['user']->status != 1) {
                throw new \Exception(XZXResponseCode::getMessage(XZXResponseCode::LOGIN_FORBIDDEN), XZXResponseCode::LOGIN_FORBIDDEN);
            }
        }

        // 验token通过
        if ($isValidToken) {

            $ext = array_merge($request->getAttribute("ext", []), [
                "user"        => [
                    'id'       => $data['user']->id,
                    'username' => $data['user']->username,
                ],
                "role"        => $data['role'],
                "createBy"    => $data['user']->username,
                "updateBy"    => $data['user']->username,
                "uid"         => $data["uid"],
                "roleId"      => $data['user']->roleId,
                "isSuperRole" => $data['user']->isSuperRole,
                "status"      => $data['user']->status,
                "mchIdList"   => $this->__getMchIdList($data['uid']),
            ]);

            CustomUtils::xzxDebug($ext);

            // 全局修改$request，后面控制器需要接受ext
            $request = $request->withAttribute("ext", $ext);
            $request = Context::set(ServerRequestInterface::class, $request);

        }
        else {
            throw new \Exception(XZXResponseCode::getMessage(XZXResponseCode::TOKEN_ERROR_CODE), XZXResponseCode::TOKEN_ERROR_CODE);
        }

        return $handler->handle($request);
    }

    private function __getMchIdList ($userId) {

        $list = $this->SysAdminMchRelationDao->getWhereList(['adminId' => $userId]);

        return array_map(function ($item) {
            return $item['mchId'];
        }, $list);
    }
}
